using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
//Added by Joseph
using System.IO; //for path class
using System.Xml;
using System.Xml.Xsl;
using System.Reflection;//for getting assembly version

namespace FOW
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        private void tsNew_Click(object sender, EventArgs e)
        {
            txtAlbumTitle.Clear();
            txtAlbumDesc.Clear();

            ImagesList.Rows.Clear();
            cmbStyles.SelectedIndex = -1;
            txtStylesDescription.Clear();
            if(PreviewBox.Image != null)
                PreviewBox.Image = null;

            toolStripStatusLabel.Text = "";

        }

        private void tsOpen_Click(object sender, EventArgs e)
        {
            //TODO: Check for album version and fail if it is not the same
            OpenFileDialog FileDlg = new OpenFileDialog();
            FileDlg.Title = "Select FOW Album";
            FileDlg.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            FileDlg.Filter = "FOW Album (*.fow) |*.fow";


            if (FileDlg.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    XmlDocument FOWAlbum = new XmlDocument();
                    FOWAlbum.Load(FileDlg.FileName);

                    txtAlbumTitle.Text = FOWAlbum.SelectSingleNode("//AlbumName").InnerText;
                    txtAlbumDesc.Text = FOWAlbum.SelectSingleNode("//AlbumDesc").InnerText;

                    txtStylesDescription.Text = "";
                    cmbStyles.SelectedIndex = Convert.ToInt16(FOWAlbum.SelectSingleNode("//AlbumStyle").InnerText);

                    XmlNodeList ImgsList = FOWAlbum.SelectNodes("//Image");

                    string ImgFullPath;
                    string ImgTitle;
                    string ImgText;

                    ImagesList.Rows.Clear();

                    foreach (XmlNode Img in ImgsList)
                    {
                        ImgFullPath = Img.SelectSingleNode("FullPath").InnerText;
                        ImgTitle = Img.SelectSingleNode("ImgTitle").InnerText;
                        ImgText = Img.SelectSingleNode("ImgDesc").InnerText;

                        ImagesList.Rows.Add();

                        Image.GetThumbnailImageAbort ImgCallBack = new Image.GetThumbnailImageAbort(ThumbnailCallback);
                        Image CurImg = Image.FromFile(ImgFullPath);
                        Image CurThumbImg = CurImg.GetThumbnailImage(95, 60, ImgCallBack, IntPtr.Zero);

                        //add to grid
                        DataGridViewRow CurRow = ImagesList.Rows[ImagesList.RowCount - 1];
                        CurRow.Cells[0].Value = CurThumbImg;
                        CurRow.Cells[1].Value = ImgTitle;
                        CurRow.Cells[2].Value = ImgText;
                        CurRow.Cells[3].Value = ImgFullPath; //this is not visible; it is used later in generating album

                        CurRow.Height = 70;

                    }

                    toolStripStatusLabel.Text = "Opened album " + FileDlg.FileName;
                }
                catch (IOException FOWException)
                {
                    MessageBox.Show(FOWException.Message, "FOW Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        //an empty callback function to create thumbnails
        private bool ThumbnailCallback()
        {
            return false;
        }

        private void tsSave_Click(object sender, EventArgs e)
        {
            Dictionary<string, string> FOWAlbumnodes = new Dictionary<string, string>();
            string ImgTitle;
            string ImgDesc;

            //if the focus is on one of the grid control then the values are not properly stord for that row
            this.txtAlbumDesc.Focus();

            FOWAlbumnodes.Clear();
            FOWAlbumnodes.Add("FOWVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString());
            FOWAlbumnodes.Add("AlbumName", txtAlbumTitle.Text);
            FOWAlbumnodes.Add("AlbumDesc", txtAlbumDesc.Text);

            FOWAlbumnodes.Add("AlbumStyle", cmbStyles.SelectedIndex.ToString());

            XmlDocument FOWAlbumDoc = new XmlDocument();
            XmlElement RootNode = FOWAlbumDoc.CreateElement("FOWAlbum");
            FOWAlbumDoc.AppendChild(RootNode);
            XmlElement AlbumNode;

            foreach (KeyValuePair<string, string> NodePair in FOWAlbumnodes)
            {
                AlbumNode = FOWAlbumDoc.CreateElement(NodePair.Key);
                AlbumNode.AppendChild(FOWAlbumDoc.CreateTextNode(NodePair.Value));
                RootNode.AppendChild(AlbumNode);
            }

            XmlElement ImgsNode = FOWAlbumDoc.CreateElement("Images");

            foreach (DataGridViewRow ImageRow in ImagesList.Rows)
            {
                XmlElement ImgNode = FOWAlbumDoc.CreateElement("Image");

                AlbumNode = FOWAlbumDoc.CreateElement("FullPath");
                AlbumNode.AppendChild(FOWAlbumDoc.CreateTextNode(ImageRow.Cells["colFullPathWithExt"].Value.ToString()));
                ImgNode.AppendChild(AlbumNode);

                ImgTitle = ImageRow.Cells["colImgTitle"].Value == null ? "" : ImageRow.Cells["colImgTitle"].Value.ToString();

                AlbumNode = FOWAlbumDoc.CreateElement("ImgTitle");
                AlbumNode.AppendChild(FOWAlbumDoc.CreateTextNode(ImgTitle));
                ImgNode.AppendChild(AlbumNode);

                ImgDesc = ImageRow.Cells["colImgTxt"].Value == null ? "" : ImageRow.Cells["colImgTxt"].Value.ToString();

                AlbumNode = FOWAlbumDoc.CreateElement("ImgDesc");
                AlbumNode.AppendChild(FOWAlbumDoc.CreateTextNode(ImgDesc));
                ImgNode.AppendChild(AlbumNode);

                ImgsNode.AppendChild(ImgNode);
            }

            RootNode.AppendChild(ImgsNode);

            SaveFileDialog FileDlg = new SaveFileDialog();
            FileDlg.Title = "Save Album";
            FileDlg.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            FileDlg.Filter = "FOW Album (*.fow) |*.fow";

            if (FileDlg.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    File.WriteAllText(FileDlg.FileName, FOWAlbumDoc.InnerXml);
                    toolStripStatusLabel.Text = "Saved Album in " + FileDlg.FileName;
                }
                catch (IOException FOWException)
                {
                    MessageBox.Show(FOWException.Message, "FOW Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }

        }

        private void tsGenerate_Click(object sender, EventArgs e)
        {
            FOW.GlobalClass.Options SelectedOption;
            string IndexPgHTMLFileName = "index.html";
            string XSLOutputFileName = "";
            string XSLFileName = "";
            string ImgXSLFileName = "";
            string OutputXMLFileName = "";
            //output will be created in user's temp directory
            string OutputDir = System.IO.Path.GetTempPath() + "FOWAlbum";
            string ResourcesDir = "/resources";
            string StyleDir = "";
            string ImagesDir = System.IO.Path.Combine(OutputDir, "images");
            string ThumbDir = System.IO.Path.Combine(OutputDir, "thumbs");
            string RelImagesDir = "images";
            string RelThumbDir = "thumbs";
            Image CurImg, CurThumbImg;
            string ImgName = ""; //name part of the image filename; fullpath is stored in gridview cell itself
            string ImgExt = ""; //ext part of the image name
            string ImgFileName = ""; //contains the full path
            string ImgTitle;
            string ImgDesc;
            string GenerateOnlyIndex = "";


            //check total images; if no images, there is no point in generating output
            int TotalImgs = ImagesList.Rows.Count;
            if (TotalImgs == 0)
            {
                MessageBox.Show("There are no images.\nPlease insert images before generating the album.", "Oops", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            //get the selected style
            if (cmbStyles.SelectedIndex != -1)
            {
                SelectedOption = (FOW.GlobalClass.Options)FOW.GlobalClass.StylesOptions[cmbStyles.SelectedIndex];
                StyleDir = SelectedOption.StyleDir;
                XSLOutputFileName = SelectedOption.OutputFileName;
                XSLFileName = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + System.IO.Path.DirectorySeparatorChar + StyleDir + System.IO.Path.DirectorySeparatorChar + SelectedOption.MainStyle;

                GenerateOnlyIndex = SelectedOption.IsOnlyIndex;
                if (GenerateOnlyIndex != "1")
                {
                    ImgXSLFileName = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + System.IO.Path.DirectorySeparatorChar + StyleDir + System.IO.Path.DirectorySeparatorChar + SelectedOption.ImgStyle;
                }
            }
            else
            {
                MessageBox.Show("No style is selected. Please select one", "No Style", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                return;
            }         
            
            //in that create a subdirectory for FOW Album;
            if (!Directory.Exists(OutputDir))
                System.IO.Directory.CreateDirectory(OutputDir);

            System.IO.Directory.SetCurrentDirectory(OutputDir);

            //create images & thumbnails folder
            if (!Directory.Exists(ImagesDir))
                System.IO.Directory.CreateDirectory(ImagesDir);

            if (!Directory.Exists(ThumbDir))
                System.IO.Directory.CreateDirectory(ThumbDir);

            toolStripStatusLabel.Text = "Starting to generate album in " + OutputDir;

            DirectoryInfo SourceResourceDir = new DirectoryInfo(System.IO.Path.GetDirectoryName(Application.ExecutablePath) + System.IO.Path.DirectorySeparatorChar + StyleDir + ResourcesDir);

            foreach (FileInfo resourcefiles in SourceResourceDir.GetFiles())
            {
                resourcefiles.CopyTo(Path.Combine(OutputDir, resourcefiles.Name), true);
            }

            #region Generate XML
            //create xml file
            OutputXMLFileName = OutputDir + System.IO.Path.DirectorySeparatorChar + "fow.xml";
            XmlTextWriter FOWXML = new XmlTextWriter(OutputXMLFileName, System.Text.Encoding.Unicode);
            Image.GetThumbnailImageAbort ImgCallback = new Image.GetThumbnailImageAbort(ThumbnailCallback);

            try
            {
                FOWXML.Formatting = Formatting.Indented;
                //write document declaration
                FOWXML.WriteStartDocument();
                //write first element
                FOWXML.WriteStartElement("Album");

                //write generic album options
                FOWXML.WriteElementString("Title", txtAlbumTitle.Text == "" ? "My Photo Album" : txtAlbumTitle.Text);
                FOWXML.WriteElementString("Description", txtAlbumDesc.Text);
                FOWXML.WriteElementString("TotalImages", TotalImgs.ToString());
                FOWXML.WriteElementString("IndexPage", IndexPgHTMLFileName);
                //write images
                FOWXML.WriteStartElement("Images");
                foreach (DataGridViewRow CurRow in ImagesList.Rows)
                {
                    //first generate the xml tags
                    FOWXML.WriteStartElement("Img");
                    ImgFileName = CurRow.Cells["colFullPathWithExt"].Value.ToString();
                    ImgName = CurRow.Index.ToString();
                    ImgExt = Path.GetExtension(ImgFileName); //contains with .

                    FOWXML.WriteElementString("ImgId", CurRow.Index.ToString());
                    FOWXML.WriteElementString("ThumbPath", RelThumbDir + System.IO.Path.DirectorySeparatorChar + ImgName + ".jpeg");
                    FOWXML.WriteElementString("ImgPath", RelImagesDir + System.IO.Path.DirectorySeparatorChar + ImgName + ImgExt);
                    FOWXML.WriteElementString("ImgName", ImgName + ImgExt);
                    ImgTitle = CurRow.Cells["colImgTitle"].Value == null ? Path.GetFileNameWithoutExtension(ImgFileName) : CurRow.Cells["colImgTitle"].Value.ToString();
                    FOWXML.WriteElementString("ImgTitle", ImgTitle);
                    ImgDesc = CurRow.Cells["colImgTxt"].Value == null ? Path.GetFileNameWithoutExtension(ImgFileName) : CurRow.Cells["colImgTxt"].Value.ToString();
                    FOWXML.WriteElementString("ImgDesc", ImgDesc);
                    FOWXML.WriteElementString("ImgPgURL", "fow" + ImgName + ".html");

                    FOWXML.WriteEndElement();

                    //now generate the images & thumbnails
                    CurImg = Image.FromFile(ImgFileName);
                    CurThumbImg = CurImg.GetThumbnailImage(93, 65, ImgCallback, IntPtr.Zero);
                    CurImg.Save(ImagesDir + System.IO.Path.DirectorySeparatorChar + ImgName + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                    CurThumbImg.Save(ThumbDir + System.IO.Path.DirectorySeparatorChar + ImgName + ".jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
                }
                //for images elem
                FOWXML.WriteEndElement();

                //this is end elem for root elem
                FOWXML.WriteEndElement();
                FOWXML.WriteEndDocument();
                FOWXML.Flush();
            }
            catch (XmlException FOWException)
            {
                //TODO: log file
                System.Diagnostics.Debug.Print(FOWException.Message);
            }
            finally
            {
                if (FOWXML != null)
                    FOWXML.Close();
            }

            #endregion

            toolStripStatusLabel.Text = "Created XML File";

            //apply xslt
            XslCompiledTransform FOWXSL = new XslCompiledTransform();
            FOWXSL.Load(XSLFileName);
            FOWXSL.Transform(OutputXMLFileName, XSLOutputFileName);


            #region Generate Image HTMLs

            if (GenerateOnlyIndex != "1")
            {
                string ImgPgURL;

                //we need to pass imgid as a parameter
                XsltArgumentList xslArg = new XsltArgumentList();

                foreach (DataGridViewRow CurRow in ImagesList.Rows)
                {
                    ImgPgURL = "fow" + CurRow.Index.ToString() + ".html";
                    FOWXSL.Load(ImgXSLFileName);
                    xslArg.Clear();
                    xslArg.AddParam("ImgId", "", CurRow.Index + 1);
                    //use streamwriter as Firefox had issue with output generated with xmlwriter
                    StreamWriter FOWImgHTML = new StreamWriter(ImgPgURL);
                    FOWXSL.Transform(OutputXMLFileName, xslArg, FOWImgHTML);
                    FOWImgHTML.Close();
                }
            }
            #endregion

            toolStripStatusLabel.Text = "Generated image HTMLs";

            //open the album
            System.Diagnostics.Process.Start(IndexPgHTMLFileName);
            toolStripStatusLabel.Text = "Album generated in " + OutputDir;
        }

        private void tsExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void tsAbout_Click(object sender, EventArgs e)
        {
            AboutBox FOWAbout = new AboutBox();
            FOWAbout.ShowDialog();
        }

        private void tsHelp_Click(object sender, EventArgs e)
        {
            Help.ShowHelp(this, helpProvider.HelpNamespace);
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tsNew_Click(sender, e);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tsOpen_Click(sender, e);
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tsSave_Click(sender, e);
        }

        private void generateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tsGenerate_Click(sender, e);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tsExit_Click(sender, e);
        }

        private void imagesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tabFOW.SelectedTab = tabFOW.TabPages[0];
        }

        private void stylesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tabFOW.SelectedTab = tabFOW.TabPages[1];
        }

        private void contentsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tsHelp_Click(sender, e);
        }

        private void btnSelectStylesTab_Click(object sender, EventArgs e)
        {
            tabFOW.SelectedTab = tabFOW.TabPages[1];
        }

        private void btnSelectImages_Click(object sender, EventArgs e)
        {
            tabFOW.SelectedTab = tabFOW.TabPages[0];
        }

        private void btnGenerateAlbum_Click(object sender, EventArgs e)
        {
            tsGenerate_Click(sender, e);
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tsAbout_Click(sender, e);
        }

        private void btnAddImage_Click(object sender, EventArgs e)
        {
            string ImageFilter = @"All image files|*.bmp;*.gif;*.jpg;*.png;*.pcx;*.tiff;*.xpm|" +
"BMP (*.bmp) |*.bmp|" +
//"GIF (*.gif) |*.gif|" +
"JPEG (*.jpg; *.jpeg) |*.jpg;*.jpeg|" +
"PNG (*.png) |*.png|" +
"PCX (*.pcx) |*.pcx|" +
"TIFF (*.tiff) |*.tiff|" +
"XPM (*.xpm) |*.xpm";

            OpenFileDialog FileDlg = new OpenFileDialog();
            FileDlg.Title = "Select an image file";
            FileDlg.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            FileDlg.Filter = ImageFilter;
            FileDlg.Multiselect = true;

            if (FileDlg.ShowDialog() == DialogResult.OK)
            {
                ProcessFiles(FileDlg.FileNames);
            }

        }

        private void btnAddFolder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog ImgDirDlg = new FolderBrowserDialog();
            string[] Filenames;
            string[] Dirs;
            ImgDirDlg.ShowNewFolderButton = false;

            if (ImgDirDlg.ShowDialog() == DialogResult.OK)
            {
                Filenames = Directory.GetFiles(ImgDirDlg.SelectedPath);
                ProcessFiles(Filenames);
                Dirs = Directory.GetDirectories(ImgDirDlg.SelectedPath, "*.*", SearchOption.AllDirectories);
                foreach (string Dir in Dirs)
                {
                    Filenames = Directory.GetFiles(Dir);
                    ProcessFiles(Filenames);
                }
            }

        }
        private void ProcessFiles(string[] FileNames)
        {
            string ImgExt;
            string ImgExtInLower;

            //filename is a full path
            foreach (string FileName in FileNames)
            {
                ImgExt = Path.GetExtension(FileName);
                ImgExtInLower = ImgExt.ToLower();

                if (ImgExtInLower == ".jpg" ||
                    //ImgExtInLower == ".gif" ||
                    ImgExtInLower == "jpeg" ||
                    ImgExtInLower == ".png" ||
                    ImgExtInLower == ".bmp" ||
                    ImgExtInLower == ".tiff" ||
                    ImgExtInLower == ".xpm" ||
                    ImgExtInLower == ".pcx")
                {
                    ImagesList.Rows.Add();

                    Image.GetThumbnailImageAbort ImgCallBack = new Image.GetThumbnailImageAbort(ThumbnailCallback);
                    Image CurImg = Image.FromFile(FileName);
                    Image CurThumbImg = CurImg.GetThumbnailImage(95, 60, ImgCallBack, IntPtr.Zero);

                    //add to grid
                    DataGridViewRow CurRow = ImagesList.Rows[ImagesList.RowCount - 1];
                    CurRow.Cells[0].Value = CurThumbImg;
                    CurRow.Cells[3].Value = FileName; //this is not visible; it is used later in generating album

                    CurRow.Height = 70;
                }
            }
        }

        private void btnClearAll_Click(object sender, EventArgs e)
        {
            ImagesList.Rows.Clear();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            //browse through styles dir and populate the styles
            //it is assumed that the styles dir = styles
            //it is checked in program.cs that the dir already exists
            string[] styleDirectories = Directory.GetDirectories("Styles");
            XmlDocument ConfigXML = new XmlDocument();
            string DisplayName;
            string Description;
            string MainStyle;
            string ImgStyle;
            string OnlyIndex;
            string PreviewImg;
            string StylesDir;
            string OutputFileName;

            foreach (string styleDir in styleDirectories)
            {
                //within each style dir, read config.xml
                ConfigXML.Load(styleDir + "/config.xml");
                DisplayName = ConfigXML.SelectSingleNode("//displayname").InnerText;
                Description = ConfigXML.SelectSingleNode("//description").InnerText;
                MainStyle = ConfigXML.SelectSingleNode("//mainxsl").InnerText;
                ImgStyle = ConfigXML.SelectSingleNode("//imgxsl").InnerText;
                OnlyIndex = ConfigXML.SelectSingleNode("//onlyindex").InnerText;
                PreviewImg = ConfigXML.SelectSingleNode("//previewimg").InnerText;
                StylesDir = ConfigXML.SelectSingleNode("//styledir").InnerText;
                OutputFileName = ConfigXML.SelectSingleNode("//outputfilename").InnerText;

                //add to arraylist
                FOW.GlobalClass.StylesOptions.Add(new FOW.GlobalClass.Options(DisplayName, Description, MainStyle, ImgStyle, OnlyIndex, PreviewImg, StylesDir, OutputFileName));

                //add to the drop down list
                cmbStyles.Items.Add(DisplayName);
            }

        }

        private void cmbStyles_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbStyles.SelectedIndex != -1)
            {
                FOW.GlobalClass.Options SelectedOption = (FOW.GlobalClass.Options)FOW.GlobalClass.StylesOptions[cmbStyles.SelectedIndex];
                txtStylesDescription.Text = SelectedOption.Description;
                string PreviewImg = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + System.IO.Path.DirectorySeparatorChar + SelectedOption.StyleDir + System.IO.Path.DirectorySeparatorChar + SelectedOption.PreviewImg;
                Image CurImg = Image.FromFile(PreviewImg);
                PreviewBox.Image = CurImg;

            }

        }

    }
}